﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sustainalytics.Entities;
using Sustainalytics.DynamicsCRMGateway;
using Sustainalytics.DynamicsCRMGateway.Entities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Client;

namespace Sustainalytics.CRMAddFakeData
{
    public class DataProvisioning 
    {
        private ICrmRepository<new_testaccount> _accountRepo;
        private ICrmRepository<new_testaccountfeature> _accountFeatureRepo;
        private ICrmRepository<new_testfeature> _featureRepo;

        private ICrmRepository<new_testaccount2> _account2Repo;
        private ICrmRepository<new_testfeature2> _feature2Repo;

        private CrmServiceContext _crmServiceContext;

        private List<new_testaccount> _newAccounts = new List<new_testaccount>();
        private List<new_testfeature> _newFeatures = new List<new_testfeature>();
        private List<new_testaccountfeature> _newAccountFeatures = new List<new_testaccountfeature>();
        private Dictionary<Guid, Tuple<new_testaccount, new_testfeature>> _newAccountFeaturesDict = new Dictionary<Guid, Tuple<new_testaccount, new_testfeature>>();
        
        private List<new_testaccount2> _newAccounts2 = new List<new_testaccount2>();
        private List<new_testfeature2> _newFeatures2 = new List<new_testfeature2>();
        private List<Tuple<Guid, Guid>> _newAccountFeatures2 = new List<Tuple<Guid, Guid>>();

        public DataProvisioning(
            ICrmRepository<new_testaccount> accountRepo,
            ICrmRepository<new_testaccountfeature> accountFeatureRepo,
            ICrmRepository<new_testfeature> featureRepo,
            ICrmRepository<new_testaccount2> account2Repo, 
            ICrmRepository<new_testfeature2> feature2Repo,
            CrmServiceContext crmServiceContext)
        {
            _accountRepo = accountRepo;
            _accountFeatureRepo = accountFeatureRepo;
            _featureRepo = featureRepo;
            _account2Repo = account2Repo;
            _feature2Repo = feature2Repo;
            _crmServiceContext = crmServiceContext;
        }

        const string _prefix = "";

        private void CleanUp()
        {
            _accountRepo.Delete(_accountRepo.ReadAll().Select(a => a.Id));
            _featureRepo.Delete(_featureRepo.ReadAll().Select(f => f.Id));
            _account2Repo.Delete(_account2Repo.ReadAll().Select(a => a.Id));
            _feature2Repo.Delete(_feature2Repo.ReadAll().Select(f => f.Id));
            _accountFeatureRepo.Delete(_accountFeatureRepo.ReadAll().Select(f => f.Id));
        }


        private void Del()
        {
            _accountFeatureRepo.Delete(new List<Guid>(){ Guid.Parse("c730528e-76b6-440c-8847-0614a2664f1c"), Guid.Parse("d5b246ce-8be7-4341-93c7-a3db123fcc76")});
        }
        private void GenerateData()
        {
            for(int i=0; i<6000; i++)
            {
                var ac = new new_testaccount()
                {
                    Name = _prefix + "Account" + i,
                    AccountId = Guid.NewGuid()
                };
                _newAccounts.Add(ac);

                var ac2 = new new_testaccount2()
                {
                    Name = _prefix + "Account" + i,
                    Account2Id = Guid.NewGuid()
                };
                _newAccounts2.Add(ac2);
            }

            for (int i = 0; i < 20; i++)
            {
                var fe = new new_testfeature()
                {
                    Name = _prefix + "Feature" + i,
                    FeatureId = Guid.NewGuid()
                };
                _newFeatures.Add(fe);

                var fe2 = new new_testfeature2()
                {
                    Name = _prefix + "Feature" + i,
                    Feature2Id = Guid.NewGuid()
                };
                _newFeatures2.Add(fe2);

            }

            for (int i = 0; i < _newAccounts.Count(); i++)
            {
                int start, end;
                if (i % 2 == 0)
                {
                    start = 0;
                    end = 2;
                }
                else
                {
                    start = 2;
                    end = 4;
                }

                for (int j = start; j < end; j++)
                {
                    var id = Guid.NewGuid();
                    _newAccountFeatures.Add(new new_testaccountfeature()
                    {
                        Id = id,
                        Account = null,
                        Feature = null
                    });
                    _newAccountFeaturesDict.Add(id, new Tuple<new_testaccount, new_testfeature>(_newAccounts[i], _newFeatures[j]));
                }
            }

            for (int i = 0; i < _newAccounts2.Count(); i++)
            {
                int start, end;
                if (i % 2 == 0)
                {
                    start = 0;
                    end = 2;
                }
                else
                {
                    start = 2;
                    end = 4;
                }
                for (int j = start; j < end; j++)
                {
                    _newAccountFeatures2.Add(new Tuple<Guid, Guid>(_newAccounts2[i].Id, _newFeatures2[j].Id));
                }
            }
        }

        public void StoreData()
        {
            try
            {
                //Del();

                //CleanUp();

                GenerateData();

                _featureRepo.Create(_newFeatures);
                _accountRepo.Create(_newAccounts);
                _accountFeatureRepo.Create(_newAccountFeatures);
                _newAccountFeatures.ForEach(x => { x.Account = _newAccountFeaturesDict[x.Id].Item1; x.Feature = _newAccountFeaturesDict[x.Id].Item2; });
                _accountFeatureRepo.Update(_newAccountFeatures);

                _feature2Repo.Create(_newFeatures2);
                _account2Repo.Create(_newAccounts2);
                
                var accountFeatureRelationship = new Microsoft.Xrm.Sdk.Relationship("new_testaccountfeature2");
                _newAccountFeatures2.GroupBy(af => af.Item1, cf => cf.Item2, (key, g) => new { AccountId = key, Features = g.ToList() }).ToList()
                    .ForEach(x => _crmServiceContext.Associate(
                        "new_testaccount2",
                        x.AccountId,
                        accountFeatureRelationship,
                        new Microsoft.Xrm.Sdk.EntityReferenceCollection(x.Features.Select(f => new EntityReference("new_testfeature2", f)).ToList())));


                Console.WriteLine("Data provisioning succeeded!");
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                Console.ReadKey();
            }
        }
    }
}
